﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Diagnostics;
using eBook.Core;
using eBook.Core.BusinessObjects;
using eBook.Core.Contracts;
using WeifenLuo.WinFormsUI.Docking;
using Win32;
using System.Reflection;
using System.IO;
using System.Text.RegularExpressions;

namespace eBook.WinApp
{
  public partial class frmImport : DockContent
  {
    private Process _readerProcess = null;
    private IBookMashup _masher;
    private ILibRepository _libRepository;
    private List<boBookInfo> _searchResult;
    private ctrlBookInfo _mashedInfoContainer;

    public frmImport()
    {
      InitializeComponent();
      txtBasePath.Text = Utils.FolderOptions.LibraryBasePath;
    }

    public frmImport(IBookMashup masher, ILibRepository libRepository) : this()
    {
      _masher = masher;
      _libRepository = libRepository;
    }

    private bool FetchClipboardText(string clpContent)
    {
      if (txtISBN10.Text == clpContent || txtISBN13.Text == clpContent)
        return false;

      bool isbnValid = false;
      if (new ISBN10(clpContent).Validate())
      {        
        txtISBN10.Text = clpContent;
        isbnValid = true;
      } else if (new ISBN13(clpContent).Validate())
      {
        txtISBN13.Text = clpContent;
        isbnValid = true;
      }

      if (isbnValid)
        MinimizeReaderProcess();

      return isbnValid;
    }

    private void MinimizeReaderProcess()
    {
      //const int SC_MINIMIZE = 61472;
      //const int SW_SHOWNORMAL = 1;
      const int SW_SHOWMINIMIZED = 2;
      //const int SW_SHOWMAXIMIZED = 3;
     
      if (_readerProcess == null)
        return;


      User32.PostMessage(_readerProcess.MainWindowHandle, ( uint ) Msgs.WM_ACTIVATE, IntPtr.Zero, 0);
      //User32.PostMessage(_readerProcess.MainWindowHandle, ( uint ) Msgs.WM_SYSCOMMAND, ( IntPtr ) SC_MINIMIZE, 0);
      User32.ShowWindowAsync(_readerProcess.MainWindowHandle, SW_SHOWMINIMIZED);
    }

    private void KillReaderProcess()
    {
      if (_readerProcess == null)
        return;
      
      try
      {
        _readerProcess.CloseMainWindow();
        _readerProcess.Kill();
        
        //_readerProcess.Close();
        //User32.SendMessage(_readerProcess.MainWindowHandle, (int)Win32.Msgs.WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
        //_readerProcess.Dispose();
      }
      catch (Exception ex)
      {
        MessageBox.Show(ex.GetType().ToString());
      }

      //System.Threading.Thread.Sleep(1000);
      _readerProcess = null;      
    }

    private void FileOpen(string fileName)
    {
      KillReaderProcess();

      _readerProcess = new Process();
      ProcessStartInfo si = new ProcessStartInfo("\"" + fileName + "\"");
      si.CreateNoWindow = false;
      _readerProcess.StartInfo = si;
      _readerProcess.Start();

      return;
    }


    private void Search()
    {
      ISBN isbn = null;
      if (!string.IsNullOrEmpty(txtISBN10.Text))
        isbn = new ISBN10(txtISBN10.Text);
      else if (!string.IsNullOrEmpty(txtISBN13.Text))
        isbn = new ISBN13(txtISBN13.Text);

      if (isbn == null || !isbn.Validate())
        return;

      tabBook.TabPages.Clear();
      txtDestination.Clear();
      _mashedInfoContainer = null;
      SearchWithISBN(isbn);
    }

    private void SearchWithISBN(ISBN isbn)
    {
      if (isbn == null)
        return;
      
      Application.DoEvents();
      try
      {        
        Cursor.Current = Cursors.WaitCursor;        
        _searchResult = new List<boBookInfo>();
        _searchResult.AddRange(_masher.GetBookInfoByISBN(isbn));

        if (_searchResult.Count > 0)
          RenderSearchResult(_searchResult);
      }
      finally
      {
        Cursor.Current = Cursors.Default;
      }
    }

    private void btnSearch_Click(object sender, EventArgs e)
    {
      string isbn = string.Empty;
      if ( !string.IsNullOrEmpty(txtISBN10.Text) )
        isbn = txtISBN10.Text;
      else if ( !string.IsNullOrEmpty(txtISBN13.Text) )
        isbn = txtISBN13.Text;

      if ( string.IsNullOrEmpty(isbn) )
        return;

      ISBN n = ISBNFactory.Create(isbn);
      this.SearchWithISBN(n);
    }

    private void RenderSearchResult(List<boBookInfo> searchResult)
    {
      tabBook.TabPages.Clear();
      foreach (var item in searchResult)
      {
        if (item == null)
          continue;

        TabPage page = new TabPage(item.InfoProvider);        
        ctrlBookInfo ctl = new ctrlBookInfo();
        ctl.DataItem = item;
        page.Controls.Add(ctl);        
        tabBook.TabPages.Add(page);
      }
    }

    private void ResetGUI()
    {
      Application.DoEvents();

      txtSource.Clear();
      txtDestination.Clear();      
      txtISBN10.Clear();
      txtISBN13.Clear();

      tabBook.TabPages.Clear();
      _mashedInfoContainer = null;

      Application.DoEvents();
    }

    private void btnMashUp_Click(object sender, EventArgs e)
    {
      if ( _mashedInfoContainer == null )
      {
        TabPage page = new TabPage("MASH");

        _mashedInfoContainer = new ctrlBookInfo();
        _mashedInfoContainer.DataItem = new boBookInfo {InfoProvider = "MASH"};
        page.Controls.Add(_mashedInfoContainer);
        tabBook.TabPages.Add(page);
        tabBook.SelectedTab = page;
      }
      
      foreach ( var result in _searchResult)
	    {
        _mashedInfoContainer.CopyFromExample(result);
	    }      
      _searchResult.Add(_mashedInfoContainer.DataItem);

      this.KillReaderProcess();
      txtDestination.Text = this.BuildNewFilePath(_mashedInfoContainer.DataItem);
    }

    private void frmImport_Load(object sender, EventArgs e)
    {
      FormFactory.Instance.MdiContainer.OnClipboardText += new ClipboardEventHandler(frmImport_OnClipboardText);
    }

    private void frmImport_OnClipboardText(object sender, ClipboardEventArgs e)
    {
      if (this.FetchClipboardText(e.Text))
      {
        //Debug.WriteLine("Will search " + e.Text);
        this.Search();
      }
    }

    private void frmImport_FormClosing(object sender, FormClosingEventArgs e)
    {
      FormFactory.Instance.MdiContainer.OnClipboardText -= new ClipboardEventHandler(frmImport_OnClipboardText);

      //txtISBN10.KeyUp -= new KeyEventHandler(OnKeyUpHandler);
      //txtISBN13.KeyUp -= new KeyEventHandler(OnKeyUpHandler);

      KillReaderProcess(); 
    }

    private void btnOpen_Click(object sender, EventArgs e)
    {
      if (dlgOpen.ShowDialog() != DialogResult.OK)
        return;

      this.ResetGUI();

      txtSource.Text = dlgOpen.FileName;
      FileOpen(dlgOpen.FileName);
      var match = new Regex(@"[0-9X\-]{13,17}").Match(dlgOpen.FileName);
      if ( !match.Success )
        return;

      Clipboard.Clear();
      Clipboard.SetText(match.Value);
    }

    private void btnImport_Click(object sender, EventArgs e)
    {
      try
      {
        Cursor.Current = Cursors.WaitCursor;
        if (_searchResult == null)
          return;

        if (_searchResult.Count == 0)
          return;

        var info = _searchResult.FirstOrDefault(x => x != null && x.InfoProvider == "MASH");
        if ( info == null )
        {
          AddLogLine("Search has not been mashed");
          //throw new Exception("Book search has not been mashed");
          return;
        }

        string basePath = Utils.FolderOptions.LibraryBasePath;
        string sourcePath = txtSource.Text;
        string destinationPath = txtDestination.Text;          
        
        var book = _libRepository.GetBookByISBN(info.ISBN);
        if ( book != null )
        {
          AddLogLine( string.Format("Book record already exists in database with BookId = {0}", book.BookID) );

          if ( book.RelativePath != string.Empty && !File.Exists(Path.Combine(basePath, book.RelativePath)) )
            AddLogLine("Book file missing");

          //throw new Exception("Book already exists");
          //return;
        }

        if ( File.Exists(destinationPath) )
        {
          AddLogLine("Book already exists in file system");
          //return;
        }

        string destinationFolder = Path.GetDirectoryName(destinationPath);
        if ( !Directory.Exists(destinationFolder) )
          Directory.CreateDirectory(destinationFolder);

        FileInfo f = new FileInfo(sourcePath);
        f.MoveTo(destinationPath);    

        if ( !basePath.EndsWith("\\") )
          basePath += "\\";
        info.Path = destinationFolder.Replace(basePath, "");
        info.FileName = f.Name;     
        
        _libRepository.SaveOrUpdateBookInfo(info);

        //book = _libRepository.GetBookByISBN(info.ISBN);    
        //_libRepository.SaveOrUpdateBook(book);
      }
      finally
      {
        Cursor.Current = Cursors.Default;
      }
    }

    private string BuildNewFilePath(boBookInfo bookInfo)
    {
      string sourceFilePath = txtSource.Text;
      string basePath = txtBasePath.Text;

      if ( string.IsNullOrEmpty(sourceFilePath) )
        return string.Empty;

      if ( !File.Exists(sourceFilePath) )
        return string.Empty;

      
      ISBN isbn = null;
      if ( !string.IsNullOrEmpty(bookInfo.ISBN10) )
        isbn = new ISBN10( bookInfo.ISBN10 );
      else
        isbn = new ISBN13(bookInfo.ISBN13);

      #region Build folder name

      string newFolderName = string.Empty;
      string[] iParts = isbn.Hyphenate().Split('-');
      if ( iParts.Length > 4 )
        newFolderName = string.Format("{0}\\{1}\\{2}\\{3}"
                                    , basePath
                                    , iParts[0]
                                    , iParts[1]
                                    , iParts[2]);
      else
        newFolderName = string.Format("{0}\\{1}\\{2}"
                                    , basePath
                                    , iParts[0]
                                    , iParts[1]);

      #endregion

      #region Build file name
      FileInfo f = new FileInfo(sourceFilePath);
      string newFilePath = string.Format("{0}\\[{1}] {2}{3}"
                                        , newFolderName
                                        , isbn.Hyphenate()
                                        , Utils.ReplaceInvalidFilenameChar(bookInfo.Title)
                                        , f.Extension);
      #endregion

      return newFilePath;
    }

    private void AddLogLine(string message)
    { 
      string logLine = string.Format("{0} {1}\n", DateTime.Now.ToString("dd.mm.yyyy HH:mm"), message);
      txtLog.AppendText(logLine);
    
    }







  }
}
